# -*-coding:utf-8-*-
'''
Created on 2016年11月23日
@author: huanglian
'''
import time
from time import sleep, localtime

import re
import serial
import os.path
import sys
from ctypes import *
from datetime import datetime
# from openpyxl import Workbook
# from openpyxl import load_workbook
import serial.tools.list_ports
from compiler.pycodegen import EXCEPT

i = 0
reload(sys)
# sys.setdefaultencoding('utf-8')  # 设置字符处理格式为utf-8，默认是ascii
casename = 'Testcase.xlsx'  # 加载用例


def Timetag():  # 记录执行时间
	return time.strftime("%Y%m%d_%H%M%S", time.localtime())


def logout(logstr, ackset):  # log输出为文本,需要参数：发送命令，AT命令返回结果）
	sys.logwrite = open(logstr, 'a')
	sys.logwrite.write(datetime.now())
	sys.logwrite.write(ackset)
	tagtime = datetime.now()
	sys.logwrite.write(tagtime.strftime('%b%d-%H:%M:%S'))
	sys.logwrite.close()


def ComList():  # 提取当前设备管理器中所有Application端口信息并返回
	port_list = list(serial.tools.list_ports.comports())
	tag = len(port_list)
	comlist = []
	for i in range(tag):
		DeviceName = port_list[i].description  # devicename
		comidNumber = port_list[i].device  # devicecomnumber
		strtag = 'Application'
		if DeviceName.find(strtag) != -1:
			comlist.append(str(comidNumber))
	return comlist


def ComList_find(com_find):  # 提取当前设备管理器中所有Application端口信息并返回
	port_list = list(serial.tools.list_ports.comports())
	tag = len(port_list)
	for i in range(tag):
		DeviceName = port_list[i]
		comidname = DeviceName[0]
		# print comidname
		if comidname == com_find:
			return True
		else:
			continue
	return False


def UartList():  # 提取当前设备管理器中所有UART端口信息
	port_list = list(serial.tools.list_ports.comports())
	tag = len(port_list)
	comlist = []
	for i in range(tag):
		DeviceName = port_list[i].description  # devicename
		comidNumber = port_list[i].device  # devicecomnumber
		strtag = 'UART'
		if DeviceName.find(strtag) != -1:
			comlist.append(str(comidNumber))
	return comlist


def ComNumber():  # 返回Application端口号，如果有多个提示手动输入
	comlist = ComList()
	if len(comlist) != 1:
		while 1:
			try:
				comid = input('Please check and input the AT com number such as \'COM1\' \n')
				return str(comid)
				break
			except Exception as Inputerror:
				print 'Input error,please try again\n'
	return str(comlist[0])


def UartNumber():  # 返回 UART 端口号，如果有多个提示手动输入
	comlist = UartList()
	if len(comlist) != 1:
		while 1:
			try:
				comid = input('Please check and input the AT com number such as \'COM1\' \n')
				return str(comid)
				break
			except Exception as Inputerror:
				print 'Input error,please try again\n'
	return str(comlist[0])


def DtrPoweron(comm):  # 开机
	comm.setDTR(0)
	print 'Power On'


def DtrPoweroff(comm):  # 关机
	comm.setDTR(1)
	print 'Power Off'


def openport(comid):  # 打开端口,返回端口comm
	while 1:
		attempts = 0
		portok = False
		while attempts < 3 and not portok:
			try:
				comm = serial.Serial()
				comm.port = comid
				comm.baudrate = 115200
				comm.timeout = 60
				portok = True
				comm.open()
				print 'Open the port success!!!', comm.port
				return comm
			except Exception:
				# print Comerror
				attempts += 1
				print 'Could not open thr port,please check the environment!!!'
				sleep(5)
				if attempts == 3:
					print 'Try for 3 times and could not open the port!!!'
					# comid.close()
					break


def closeport(comm):  # 关闭端口
	comm.close()


def SendAT(comm, SendAT, TimeDelay = 0.5):  # comid为字符格式，例如'com32'
	comm.flushInput()
	comm.flushOutput()
	comm.write(SendAT + '\r\n')
	sleep(TimeDelay)
	readNo = comm.inWaiting()
	ackstr = comm.read(readNo)
	# comid.close()
	return ackstr


def SendFixedAT(comid, testtimes):  # comid为字符格式，例如'com32'
	comm = openport(comid)
	teststr = ['ATE', 'AT+CFUN=1', 'AT+MODODR=1', 'AT+CSQ', 'AT+CPIN?', 'AT+CGDCONT?', 'AT+PSRAT', 'AT+MODODR=3',
			   'AT+CREG?', 'ATI', 'AT+CIMI', 'AT+ICCID', 'AT+COPS?', 'AT+CFUN=0']
	for i in range(1, testtimes + 1, 1):  # 需要控制此函数执行时间
		for x in teststr:
			writeNo = 0
			writeNo = comm.write(x + '\r\n')
			sleep(0.1)
			readNo = comm.inWaiting()
			ackstr = comm.read(readNo)
			print ackstr
		print 'Test times:', i
	# comm.close()


def pppconnect():  # 调用系统name为‘3gnet’的拨号端口发起拨号
	return os.system('rasdial "3gnet" "" ""')  # 拨号,Dial-up Connection为网络连接中连接名称


def pppdisconnect():  # 调用系统name为‘3gnet’的拨号端口断开拨号
	os.system('rasphone -h "3gnet"')


def ppprecyle():  # 循环连网断网
	os.system('rasdial "3gnet" "" ""')
	sleep(10)
	os.system('rasphone -h "3gnet"')
	sleep(1)


def cfuncheck(comm):  # cfun1返回1，cfun0返回0
	ackstr = SendAT(comm, 'AT+CFUN?\r\n')
	print ackstr
	sStr1 = '1'
	sStr2 = '0'
	if ackstr.find(sStr1) != -1:
		print 'CFUN:1'
		return 1
	if ackstr.find(sStr2) != -1:
		print 'CFUN:0'
		return 0


def registcheck(comm):  # 注册返回1未注册返回0
	ackstr = SendAT(comm, 'AT+PSRAT\r\n')
	print ackstr
	ackstr.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '')
	print ackstr
	ackstr = ackstr.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '').replace('OK',
																								   '')  # 格式化到第一个网络状态字符
	ackstr = ackstr.replace('AT+PSRAT+PSRAT:', '')
	# print ackstr
	# sStr1 = 'LTEFDD,LTETDD,HSUPA,HSPA+,TDSCDMA,GSM,EDGE,GPRS,EVDO,EHRPD,CDMA'
	sStr1 = 'LTEFDD,LTETDD'
	if sStr1.find(ackstr) != -1:
		print 'Regist Success!'
		return 1
	else:
		return 0


def Connectcheck():
	import socket
	while 1:
		try:
			s = socket.gethostbyname("baidu.com")
		except Exception as e:
			print '网络连接失败'
			break
			return 0
		# else:
		print '网络连接通畅'
		return 1
		sleep(1)


def SimStresstest(comm):  # SIM压力测试
	i = 0
	while 1:
		if registcheck(comm) == 1:
			SendAT(comm, 'AT+CFUN=0')
			sleep(3)
			i = i + 1
			print 'test times:', i
			print datetime.now()
			SendAT(comm, 'AT+CFUN=1')
		else:
			sleep(1)
			print 'FAIL'
			SendAT(comm, 'AT+CFUN=1')
			sleep(1)


def AtStresstest(comm, sendstr, exceptstr):  # 发送命令并与期望结果对比，记录成功、失败次数
	i = 0
	j = 0
	while 1:
		str1 = SendAT(comm, sendstr)
		print str1
		str2 = exceptstr
		str1 = str1.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '')
		print 'Test Rusult:\n', str1
		str2 = str2.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '')
		print 'Except Rusult:\n', str2
		if str1 == str2:
			print 'PASS'
			i = i + 1
		else:
			print 'FAIL'
			j = j + 1
		sleep(1)
		print 'success times:', i
		print 'fail times:', j


def SendATTest(comm):  # 读取excel发送AT保存结果
	report = Workbook()  # 建结果文件
	reportpage = report.create_sheet('at_testresult', 0)  # 首页新建表
	case = load_workbook(filename = casename)  # 加载用例
	casepage = case.active

	reportpage['A1'] = 'Case ID'
	reportpage['B1'] = 'Case Grade'
	reportpage['C1'] = 'Send AT'
	reportpage['D1'] = 'Test Result'
	i = 2
	while 1:
		riteNo = 0
		caseid = 'A' + str(i)  # case id tag AI
		casegradeid = 'B' + str(i)  # case grade tag BI
		SendATid = 'C' + str(i)  # send at tag CI
		testresultid = 'D' + str(i)  # testresult id DI

		reportpage[caseid] = str(casepage[caseid].value)  # 复制用例编号AI
		reportpage[casegradeid] = str(casepage[casegradeid].value)  # 复制用例等级BI
		# tabtagc='B'+str(i)#读取预期结果命令位置坐标BI
		sendstr = str(casepage[SendATid].value)  # 读取发送命令
		print 'SendAT:\n', sendstr
		if sendstr == 'None':
			break
		writeNo = comm.write(sendstr + '\r\n')
		sleep(1)
		readNo = comm.inWaiting()
		ackstr = comm.read(readNo)
		ackstr = ackstr[writeNo - 1:]  # 截取发送命令外的字符串,去掉收个换行
		reportpage[SendATid] = sendstr  # 写入发送命令记录坐标BI
		reportpage[testresultid] = ackstr  # 写入执行结果位置坐标DI
		i = i + 1
	# comm.close()
	report.save('Testresult_' + Timetag() + '.xlsx')
	print 'Test Finish!'


def AutoTest(comm):  # 读取excel发送AT保存结果和比较值
	report = Workbook()  # 建结果文件
	reportpage = report.create_sheet('at_testresult', 0)  # 首页新建表
	case = load_workbook(filename = casename)  # 加载用例
	casepage = case.active
	reportpage['A1'] = 'Case ID'
	reportpage['B1'] = 'Case Grade'
	reportpage['C1'] = 'Send AT'
	reportpage['D1'] = 'Except Result'
	reportpage['E1'] = 'Test Result'
	reportpage['F1'] = 'Result'
	i = 2
	while 1:
		riteNo = 0
		caseid = 'A' + str(i)  # case id tag AI
		casegradeid = 'B' + str(i)  # case grade tag BI
		SendATid = 'C' + str(i)  # send at tag CI
		exceptresultid = 'D' + str(i)  # except resultid DI
		testresultid = 'E' + str(i)  # testresult id EI
		resultid = 'F' + str(i)  # result id FI

		reportpage[caseid] = str(casepage[caseid].value)  # 复制用例编号AI
		reportpage[casegradeid] = str(casepage[casegradeid].value)  # 复制用例等级BI
		sendstr = str(casepage[SendATid].value)  # 读取发送命令
		print 'SendAT:\n', sendstr
		if sendstr == 'None':
			break
		writeNo = comm.write(sendstr + '\r\n')
		sleep(0.1)
		readNo = comm.inWaiting()
		ackstr = comm.read(readNo)
		ackstr = ackstr[writeNo - 1:]  # 截取发送命令外的字符串,去掉收个换行
		reportpage[SendATid] = sendstr  # 写入发送命令记录坐标CI
		reportpage[exceptresultid] = str(casepage[exceptresultid].value)  # 复制期望结果DI
		reportpage[testresultid] = ackstr  # 写入执行结果位置坐标EI

		str1 = str(reportpage[testresultid].value)  # 执行结果
		str2 = str(reportpage[exceptresultid].value)  # 期望结果
		str1 = str1.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '')
		print 'Test Rusult:\n', str1
		# print len(str1)
		str2 = str2.replace(' ', '').replace('\n', '').replace('\t', '').replace('\r', '')
		print 'Except Rusult:\n', str2
		# print len(str2)
		if str1 == str2:
			reportpage[resultid] = 'PASS'
			print 'PASS'
		else:
			reportpage[resultid] = 'FAIL'
			print 'FAIL'
		i = i + 1
	# comm.close()
	report.save('Testresult_' + Timetag() + '.xlsx')
	print 'Test Finish!'


class Init:
	def __init__(self, comm, SheetName, dut = 'module'):
		self.comm = comm  # 发送命令使用串口
		self.dut = dut  # 需要清除的模块/SIM卡
		self.SheetName = SheetName  # 根据测试页面执行初始化

	def output_close(self):  # 关闭上报信息
		# 抑制信息上报的命令行加入该列表
		cmds = ['AT+NWMINDEN=0', 'AT+URCIND=0', 'AT+SIGNALIND=0', 'AT+INITDS=0', 'at+psdialind=0', 'AT+NWTYPEIND=0']
		try:
			for cmd in cmds:
				# print cmd
				SendAT(self.comm, cmd)
		except:
			self.comm.close()
			print u'关闭信息上报失败 ...'
		print u'关闭信息上报 ...'

	def get_phonebook_index(self, i):  # 获取一条已存储的电话本索引
		ret1 = 'at+cpbr=' + str(i)
		result = SendAT(self.comm, ret1, 0.1)
		if result.find('CPBR') != -1:
			return i

	def get_phonebook_num(self):  # 获取当前已存储的电话本总数
		ret = 'at+cpbs?'
		ret = SendAT(self.comm, ret)
		counts = re.search('\d+', ret)
		counts = int(counts.group())
		return counts

	def get_phonebook_list(self):  # 获取全部已存储的电话本信息索引列表

		counts = self.get_phonebook_num()
		# print counts

		ret = 'at+cpbw=?'
		ret = SendAT(self.comm, ret)
		p = re.compile('1-(\d+)')
		ret = p.findall(ret)
		# ret = int(ret[1])
		# print ret
		ListphonebookIndex = []
		count = 0  # 用来记录当前已查找到的电话薄数量
		for i in range(1, int(ret[0]) + 1):
			if count >= counts:
				break
			if self.get_phonebook_index(i) is None:  # 电话本为空不处理
				continue
			else:
				ListphonebookIndex.append(i)
				count += 1
			# print ListphonebookIndex
		# print ListphonebookIndex
		return ListphonebookIndex

	def del_phonebook(self, phonebook_index, pb_count):  # 删除一条电话本记录
		ret = 'at+cpbw=' + str(phonebook_index)
		SendAT(self.comm, ret, 2)  # 电话本写入需要2S才能保证返回成功
		if not (pb_count % 35):
			print '.'
		else:
			print '.',

	# print ret

	def delphonebook_sim(self):  # 删除SIM卡中电话本记录
		ret = 'AT+CPBS="SM"'
		SendAT(self.comm, ret)

		# 获取SIM卡当前已有电话簿信息
		print u'读取SIM卡电话本信息 ...'
		phonebooks = self.get_phonebook_list()

		# 计算列表长度，打点换行使用
		pb_count = 1
		# print ms_count

		# 删除电话本
		print u'删除SIM卡电话本信息 ...'
		for phonebook in phonebooks:
			self.del_phonebook(phonebook, pb_count)
			pb_count += 1

	def delphonebook_module(self):  # 删除模块中电话本记录
		ret = 'AT+CPBS="ME"'
		SendAT(self.comm, ret)

		# 获取模块当前已有电话簿信息
		print u'读取模块电话本信息 ...'
		phonebooks = self.get_phonebook_list()

		# 计算列表长度，打点换行使用
		pb_count = 1
		# print ms_count

		# 删除电话本
		print u'删除模块电话本信息 ...'
		for phonebook in phonebooks:
			self.del_phonebook(phonebook, pb_count)
			pb_count += 1

	def del_phonebooks(self, dut):  # 清除电话本
		if 'sim' == dut:
			self.delphonebook_sim()
		else:
			self.delphonebook_module()

		print 'Done'

	def init_pb_module(self):  # 模块初始化
		try:
			self.del_phonebooks('module')
		except:
			print u'模块初始化失败！'

	def init_pb_sim(self):  # SIM卡初始化
		try:
			self.del_phonebooks('sim')
		except:
			print u'SIM卡初始化失败！'

	def del_message(self, dut = 'module'):
		'''
		删除短信息
		:return:
		'''
		if 'sim' == dut:
			ret = 'at+cpms="sm","sm","sm"'
			print(u'SIM短信初始化...')
		else:
			ret = 'at+cpms="me","me","me"'
			print(u'模块短信初始化...')
		SendAT(self.comm, ret)
		ret = 'at+cmgd=?'
		ret = SendAT(self.comm, ret)
		# p = re.compile(r'\((\d.*)\),')
		p = re.compile(r'\d+')
		ms_list = p.findall(ret)
		ms_list = ms_list[:-2]  # 这里正则匹配还有点不完善，最后两位需要删除
		# ms_list = ret[0].split(',')  # 匹配格式为['1', '2', ...'18']
		# ms_list = map(int, ms_list)  # 直接转为int
		ms_count = 1  #打点计数使用
		for ms in ms_list:
			try:
				ret = 'at+cmgd=' + ms
				SendAT(self.comm, ret)
				if ms_count % 35:
					print '.',
				else:
					print '.'
				ms_count += 1
			except:
				print (u'删除第 %s 条短信失败' % ms)
				continue  # 短信删除异常不退出，继续处理后续短信
		print('Done')

	def init_mg_module(self):
		self.del_message('module')

	def init_mg_sim(self):
		self.del_message('sim')

	def init_system(self):  # 系统初始化
		print '*' * 70
		print u'【' + self.SheetName + u'】 测试初始化开始 ...'

		self.output_close()

		if "phonebook".upper() == self.SheetName:
			self.init_pb_module()
			self.init_pb_sim()
		elif "message".upper() == self.SheetName:
			self.init_mg_module()
			self.init_mg_sim()
		else:
			pass

		print u'【' + self.SheetName + u'】 测试初始化完成 ...'
		print '*' * 70
